-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RichText: selectionChange: bind on focus, unbind on blur #12480
Conversation
@@ -354,6 +347,12 @@ export class RichText extends Component { | |||
if ( unstableOnFocus ) { | |||
unstableOnFocus(); | |||
} | |||
|
|||
document.addEventListener( 'selectionchange', this.onSelectionChange ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What of these lines then?
gutenberg/packages/editor/src/components/rich-text/index.js
Lines 394 to 397 in dd331b3
// Ensure it's the active element. This is a global event. | |
if ( ! this.isActive() ) { | |
return; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we should be able to remove this.
} | ||
|
||
onBlur() { | ||
document.removeEventListener( 'selectionchange', this.onSelectionChange ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess blur
, despite bubbling, doesn't fire when moving between elements in the same contenteditable
?
https://codepen.io/aduth/pen/VVqOmq?editors=1111
(In other words, I suspected there could be an issue, but it doesn't appear so)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it shouldn't, it starts at the contenteditable
element.
@@ -392,11 +386,6 @@ export class RichText extends Component { | |||
* Handles the `selectionchange` event: sync the selection to local state. | |||
*/ | |||
onSelectionChange() { | |||
// Ensure it's the active element. This is a global event. | |||
if ( ! this.isActive() ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd noted it elsewhere, but there's a small difference between isActive
and onFocus
in that the prior was testing the div
wrapper as the active element, the latter exclusively applied to the TinyMCE element (i.e. not considering toolbars and such). When last I tested this, I recall it being a reasonable difference in that (a) all other elements are non-visual or slot-rendered and (b) are not relevant to the selection anyways.
Does that sound accurate to you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I think both are checking the contenteditable
element? this.editableRef
is the contenteditable
element, and onFocus
is a listener on that element. Maybe you're thinking about setFocusedElement
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I think both are checking the
contenteditable
element?this.editableRef
is thecontenteditable
element, andonFocus
is a listener on that element. Maybe you're thinking aboutsetFocusedElement
?
Ah! I am!
I still think we should consolidate these, as having multiple concepts of focus here is particularly confusing for me, but it's not relevant to the change proposed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, tbh I'm not sure why there's something like setFocusedElement
on the wrapper...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My hope was that at some point, we could get rid of the wrapper, at least in the sense of having it be a <Fragment>
instead of an actual DOM div
node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@iseulde, out of curiosity, do you have an idea if there would be a way to detect that you are still editing a given
In other words, whatever you do related to editing, we would need to be able to identify a currently active |
Sounds like this is what |
This is where we want it to be. It's not yet there :( The issue is mostly when there are other components like |
But this PR doesn't cause any issues right? |
I don't think so. I just wanted to discuss further improvements :) |
There's an issue with the changes here, in that if the component unmounts while it's focused and before it's blurred, an error can be logged. This can be seen when merging two blocks, for example.
I'll plan to submit a fix soon, which would be to call to remove the event handler still in |
See: #12817 (now merged) |
Description
This PR is an attempt to decrease the work done on a key press. Every key press is eventually followed by (several) selection change events. Every
RichText
instance has a listener on this global event, all of which will be called multiple times after a key press. This is not significant for a few instances, but it becomes quite noticeable if there are a huge amount of instances.The solution is to only add the listener on focus, then remove again on blur.
Testing on with this post I notice one selection change event takes on average 9ms to complete. With this PR it takes on average 0.3ms.
How has this been tested?
Screenshots
Types of changes
Checklist: